package com.zxy.ziems.server.energy.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.zxy.btp.common.util.JsonUtils;
import com.zxy.ziems.server.classify.pojo.entity.Classify;
import com.zxy.ziems.server.device.pojo.entity.DeviceEntity;
import com.zxy.ziems.server.dto.DeviceMeasureDateGroupDto;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Copyright (C),
 * @ClassName: WetDryExcelExportUtil
 * @Author: yanzhiwei
 * @Description:
 * @Date: 2024/8/26 13:46
 */
@Slf4j
public class WetDryExcelExportUtil {

    private Integer jiaojiebanrizhiSheet = 0;

    private Pattern p = Pattern.compile("\\d+");


    public void complexFillWithTable1(HttpServletResponse response, String itemName, List<Classify> classifyList, List<DeviceEntity> devicePropertyAllList, List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList) {


        String key = null;

        Matcher m = p.matcher(itemName);

        while (m.find()) {
            key = m.group();
        }

        String filename = key + "号楼室外工况.xlsx";
//        String encodedFilename = null;
//        try {
//            encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
//        } catch (UnsupportedEncodingException e) {
//            throw new RuntimeException(e);
//        }
//        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFilename);
//        String fileName = "example.txt";
// 确保文件名编码正确并且转义了特殊字符
        String encodedFileName = null;
        try {
            encodedFileName = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");


        response.setContentType("application/vnd.ms-excel");

        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        // {} 代表普通变量 {.} 代表是list的变量
        // 这里模板 删除了list以后的数据，也就是统计的这一行


        // 这里 会填充到第一个sheet， 然后文件流会自动关闭
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

//        log.info(WetDryExcelExportUtil.class.getResource("").toString());
//        log.info(WetDryExcelExportUtil.class.getResource("/").toString());
//        log.info(.toString());
//        log.info(WetDryExcelExportUtil.class.getClassLoader().getResource("/").getFile();
//        String file = WetDryExcelExportUtil.class.getClassLoader().getResource("template/wetdry" + key + ".xlsx").getFile();

        ClassPathResource classPathResource = new ClassPathResource("template/wetdry" + key + ".xlsx");

        // 这里 会填充到第一个sheet， 然后文件流会自动关闭
        try (ServletOutputStream outputStream = response.getOutputStream(); InputStream inputStream = classPathResource.getInputStream()) {
//            String fileName = getGenPath();
//            ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(inputStream).build();
            ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build();

            genExcel1(key, excelWriter, classifyList, devicePropertyAllList, deviceMeasureDateGroupDtoList);

            Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
            //设置强制计算公式：不然公式会以字符串的形式显示在excel中
            workbook.setForceFormulaRecalculation(true);


            excelWriter.finish();
        } catch (Exception e) {
            log.error("exportByTemplate-导出失败", e);
        }


        // 总体上写法比较复杂 但是也没有想到好的版本 异步的去写入excel 不支持行的删除和移动，也不支持备注这种的写入，所以也排除了可以
        // 新建一个 然后一点点复制过来的方案，最后导致list需要新增行的时候，后面的列的数据没法后移，后续会继续想想解决方案

    }

//    public static void main(String[] args) {
//        ;
//        System.out.println(System.getProperty("user.dir"));
//    }

    private List<Map<String, String>> genExcel1(String key, ExcelWriter excelWriter, List<Classify> classifyList, List<DeviceEntity> devicePropertyAllList, List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList) {

        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        //设置背景颜色
        contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE1.getIndex());
        //设置填充模式
        contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);


        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(contentWriteCellStyle, contentWriteCellStyle);


        WriteSheet writeSheet = EasyExcel.writerSheet(jiaojiebanrizhiSheet).automaticMergeHead(true).
                registerWriteHandler(horizontalCellStyleStrategy).
                build();


        List<Map<String, String>> list = new ArrayList<>();
        switch (key) {
            case "1":
                list = data1(classifyList, devicePropertyAllList, deviceMeasureDateGroupDtoList);
                break;
            case "5":
                list = data5(classifyList, devicePropertyAllList, deviceMeasureDateGroupDtoList);
                break;
        }

        log.info("export -> {}", JsonUtils.toJSONString(list));

        // 直接写入数据
        excelWriter.fill(list, writeSheet);


        // excelWriter.fill(data(), writeSheet);

//        // 写入list之前的数据
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("title", "1号楼");
//
//        excelWriter.fill(map, writeSheet);

        return null;
    }


    private List<Map<String, String>> data1(List<Classify> classifyList, List<DeviceEntity> deviceEntityList, List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList) {

        List<Map<String, String>> list = new ArrayList<>();


        Map<String, String> classMap = classifyList.stream().collect(Collectors.toMap(m -> m.getClassifyName(), m -> m.getClassifyId()));
        for (DeviceEntity deviceEntity : deviceEntityList) {
            log.info("{}===>{}", deviceEntity.getName(), deviceEntity.getId());
        }
        Map<String, String> deviceMap = deviceEntityList.stream().collect(Collectors.toMap(m -> m.getName(), m -> m.getId()));
        Map<String, List<DeviceMeasureDateGroupDto>> collect = deviceMeasureDateGroupDtoList.stream().collect(Collectors.groupingBy(m -> m.getDayStr()));

        collect = collect.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (e1, e2) -> e1,
                        LinkedHashMap::new));


        for (String s : collect.keySet()) {
            List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList1 = collect.get(s);
            DeviceMeasureDateGroupDto deviceMeasureDateGroupDto = deviceMeasureDateGroupDtoList1.get(0);

            Map m = new HashMap<String, String>();
            if (deviceMeasureDateGroupDto != null) {
                m.put("date", deviceMeasureDateGroupDto.getDayStr());
            }
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "干球温度(℃)", m, "averageDry");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_DB_1_R_AR_301", m, "dry1");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_DB_1_R_AR_302", m, "dry2");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_DB_1_R_AR_303", m, "dry3");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_DB_1_R_AR_304", m, "dry4");

            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "湿球温度(℃)", m, "averageWet");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_WB_1_R_AR_301", m, "wet1");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_WB_1_R_AR_302", m, "wet2");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_WB_1_R_AR_303", m, "wet3");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_WB_1_R_AR_304", m, "wet4");

            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "露点(℃)", m, "averageDew");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "DT_DP_1_R_AR_301", m, "dew1");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "DT_DP_1_R_AR_302", m, "dew2");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "DT_DP_1_R_AR_303", m, "dew3");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "DT_DP_1_R_AR_304", m, "dew4");

            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "风速(m/s)", m, "windSpeed");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "风向(°)", m, "windDirection");
//            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "风速", m, "dew1");

            list.add(m);

        }

        return list;
    }


    /**
     * 5号楼数据
     *
     * @param classifyList
     * @param deviceEntityList
     * @param deviceMeasureDateGroupDtoList
     * @return
     */
    private List<Map<String, String>> data5(List<Classify> classifyList, List<DeviceEntity> deviceEntityList, List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList) {

        List<Map<String, String>> list = new ArrayList<>();


        Map<String, String> classMap = classifyList.stream().collect(Collectors.toMap(m -> m.getClassifyName(), m -> m.getClassifyId()));
        for (DeviceEntity deviceEntity : deviceEntityList) {
            log.info("{}===>{}", deviceEntity.getName(), deviceEntity.getId());
        }
        Map<String, String> deviceMap = deviceEntityList.stream().collect(Collectors.toMap(m -> m.getName(), m -> m.getId()));
        Map<String, List<DeviceMeasureDateGroupDto>> collect = deviceMeasureDateGroupDtoList.stream().collect(Collectors.groupingBy(m -> m.getDayStr()));

        collect = collect.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (e1, e2) -> e1,
                        LinkedHashMap::new));


        for (String s : collect.keySet()) {
            List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList1 = collect.get(s);
            DeviceMeasureDateGroupDto deviceMeasureDateGroupDto = deviceMeasureDateGroupDtoList1.get(0);

            Map m = new HashMap<String, String>();
            if (deviceMeasureDateGroupDto != null) {
                m.put("date", deviceMeasureDateGroupDto.getDayStr());
            }
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "干球温度(℃)", m, "averageDry");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_5_R_AR_CUB_301_1", m, "dry1");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "TT_5_R_AR_CUB_301_2", m, "dry2");

            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "湿球温度(℃)", m, "averageWet");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "Twb_5_R_AR_CUB_301_1", m, "wet1");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "Twb_5_R_AR_CUB_301_2", m, "wet2");

            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "露点(℃)", m, "averageDew");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "Tdp_5_R_AR_CUB_301_1", m, "dew1");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "Tdp_5_R_AR_CUB_301_2", m, "dew2");

            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "风速(m/s)", m, "windSpeed");
            getValue(classMap, deviceMap, deviceMeasureDateGroupDtoList1, "风向((°))", m, "windDirection");
            list.add(m);

        }

        return list;
    }

    private void getValue(Map<String, String> classMap, Map<String, String> deviceMap, List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList1, String name
            , Map map, String excelKey) {
        String key;
        if (classMap.get(name) != null) {
            key = classMap.get(name);
        } else if (deviceMap.get(name) != null) {
            key = deviceMap.get(name);
        } else {
            map.put(excelKey, "");
            return;
        }

        DeviceMeasureDateGroupDto deviceMeasureDateGroupDto = deviceMeasureDateGroupDtoList1.stream().filter(m -> m.getDeviceId().equals(key)).findAny().orElse(null);
        if (deviceMeasureDateGroupDto != null) {
            map.put(excelKey, deviceMeasureDateGroupDto.getStatistic().setScale(2, RoundingMode.HALF_UP));
        } else {
            map.put(excelKey, "");
        }
    }


}
